module basic(
	input wire clr, 			// 1
	input wire t3,				// 83
	input wire [2:0] sw,		// 6 5 4
	input wire [3:0] ir,		// 11 10 9 8
	input wire w1,w2,w3,		// 12 15 16
	input wire c,z,				// 2 84

    output wire drw,			// 20
    output wire pcinc,			// 21
    output wire lpc, lar,		// 22 25
    output wire pcadd,			// 18
    output wire arinc,			// 24
    output wire selctl,			// 52
    output wire memw,			// 27
    output wire stop,			// 28
    output wire lir,			// 29
    output wire ldz,ldc,		// 30 31
    output wire cin,			// 33
    output wire [3:0] s,		// 37 36 35 34
    output wire m,				// 39
    output wire abus,sbus,mbus,	// 40 41 44
    output wire short,long,		// 45 46
    output wire [3:0] sel		// 51 50 49 48
);
	// ===== SWC SWB SWA decode =====
	wire prog  = (sw==3'b000);
	wire reg_w = (sw==3'b100);
	wire reg_r = (sw==3'b011);
	wire mem_w = (sw==3'b001);
	wire mem_r = (sw==3'b010);
	
	// ===== ins decode =====
    wire nop     = (ir == 4'b0000) && prog && ph;
    wire add     = (ir == 4'b0001) && prog && ph;
    wire sub     = (ir == 4'b0010) && prog && ph;
    wire and_ins = (ir == 4'b0011) && prog && ph; 
    wire inc     = (ir == 4'b0100) && prog && ph;
    wire ld      = (ir == 4'b0101) && prog && ph;
    wire st      = (ir == 4'b0110) && prog && ph;
    wire jc      = (ir == 4'b0111) && prog && ph;
    wire jz      = (ir == 4'b1000) && prog && ph;
    wire jmp     = (ir == 4'b1001) && prog && ph;
    wire out_ins = (ir == 4'b1010) && prog && ph;  // expanded
    wire xor_ins = (ir == 4'b1011) && prog && ph;  // expanded
    wire cmp     = (ir == 4'b1100) && prog && ph;  // expanded
    wire mov     = (ir == 4'b1101) && prog && ph;  // expanded
    wire stp     = (ir == 4'b1110) && prog && ph; 

	// ===== phase =====
	reg ph;

	// ===== "st0 st1 sst0" -> "ph" =====
	always @(negedge t3,negedge clr)
	begin
		if(!clr)
		begin
			ph <= 1'b0;
		end
		else
		begin
			if(!ph&&((reg_w && w2) || ((mem_r || mem_w ) && w1)||(prog && w2)))
			begin
				ph <= 1'b1;
			end
			else if(ph && reg_w && w2)
			begin
				ph <= 1'b0;
			end
		end
	end

	// ===== output signals ===== 
	// ===== register selection =====
	assign sel[3] = (reg_w && ((w1 || w2) && ph)) || (reg_r && w2);
	assign sel[2] = reg_w && w2;
	assign sel[1] = (reg_w && ((w1 && !ph) || (w2 && ph))) || (reg_r && w2);
	assign sel[0] = (reg_w && w1) || (reg_r && (w1 || w2));
	assign selctl = ((mem_w || mem_r) && w1) || ((reg_r || reg_w) && (w1 || w2));

	// ===== data =====
	assign drw    = ((add || sub || and_ins || inc || xor_ins || mov) && w1) || (ld && w2) || (reg_w && (w1 || w2));
	
	// ===== memory control =====
	assign memw   = (st && w2) || (mem_w && w1 && ph);
	assign lar    = ((ld || st) && w1) || ((mem_w || mem_r) && w1 && !ph);
	assign arinc  = (mem_w || mem_r) && w1 && ph;
	
	// ===== PC control =====
	assign pcinc  = ((nop || add || and_ins || out_ins  || sub || inc) && w1) || ((st || jmp || mov || cmp || xor_ins) && w2) || 
				    (prog && w2 && !ph) || (jc && ((w1 && !c) || (w3 && c))) || (jz && ((w1 && !z) || (w3 && z))) ||
				    (ld && w3);
	assign lpc    = (jmp && w1) || (prog && w1 && !ph);
	assign pcadd  = ((jc && c) || (jz && z)) && w1;
	
	// ===== IR control =====
	assign lir    = ((nop || add || and_ins || out_ins || mov || sub || inc|| cmp|| xor_ins) && w1) || ((st || jmp   ) && w2) || 
			        (jc && ((w1 && !c) || (w3 && c))) || (jz && ((w1 && !z) || (w3 && z))) 
			        || (ld && w3) || (prog && w2 && !ph);
        
	// ===== ALU control =====
	assign s[3]   = ((add || and_ins || ld || jmp || out_ins || mov) && w1) || st;
	assign s[2]   = (sub || st || jmp || xor_ins || cmp) && w1;
	assign s[1]   = ((sub || and_ins || ld || jmp || out_ins || xor_ins || cmp || mov) && w1) || st;
	assign s[0]   = (add || and_ins || st || jmp) && w1;
	assign ldc    = (add || sub || inc || cmp) && w1;
	assign ldz    = (add || sub || and_ins || xor_ins || inc || cmp) && w1;
	assign cin    = add && w1;
	assign m      = ((and_ins || ld || jmp || out_ins || xor_ins || mov) && w1) || st;
	
	// ===== bus control =====
	assign abus   = ((add || sub || and_ins || inc || ld || jmp || out_ins || xor_ins || mov) && w1) || st;
	assign sbus   = (reg_w && (w1 || w2)) || (mem_w && w1) || ((mem_r || prog) && w1 && !ph);
	assign mbus   = (ld && w2) || (mem_r && w1 && ph);
	
	// ===== clock control =====
	assign short  = ((mem_r || mem_w) && w1)  || 
				    ((nop || add || and_ins || out_ins || stp || sub ||inc) && w1)
				    || (jc && w1 && !c) || (jz && w1 && !z); 
	assign long   = (ld && w2) || (jc && w2 && c) || (jz && w2 && z);
	assign stop   = (stp && w1) || ((reg_r || reg_w) && (w1 || w2)) || ((mem_r || mem_w) && w1) ;

endmodule